package com.example.widget_lib.widget.timeruler;

import com.example.widget_lib.utils.AttrUtils;
import com.example.widget_lib.utils.PxUtil;
import ohos.agp.animation.AnimatorValue;
import ohos.agp.components.AttrSet;
import ohos.agp.components.Component;
import ohos.agp.render.Canvas;
import ohos.agp.render.Paint;
import ohos.agp.render.Path;
import ohos.agp.utils.Color;
import ohos.agp.utils.Point;
import ohos.agp.utils.RectFloat;
import ohos.agp.utils.TextAlignment;
import ohos.app.Context;
import ohos.eventhandler.EventHandler;
import ohos.eventhandler.EventRunner;
import ohos.media.image.common.Rect;
import ohos.multimodalinput.event.TouchEvent;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Locale;


/**
 * 时间刻度尺view
 */
public class TimeRulerView extends Component implements Component.DrawTask, Component.TouchEventListener {

    private static final int HOUR = 24;//1小时刻度
    private static final int HALFHOUR = 48;//半小时刻度
    private static final int FIFTEENMIN = 96;//15分钟刻度
    private static final int FIVEMIN = 288;//5分钟刻度
    private static final int MIDDLE = HOUR + (FIVEMIN - HOUR) / 2;//156
    private static final int TOPMIDDLE = MIDDLE + (FIVEMIN - MIDDLE) / 2;//222
    private static final int DOWNMIDDLE = HOUR + (MIDDLE - HOUR) / 2;//90
    private static final double TOUCH_SLOP = 1.0F;//避免用户误操作的阈值

    private Context mContext;
    private SimpleDateFormat formatterMove = new SimpleDateFormat("HH:mm:ss", Locale.getDefault());
    /**
     * 24小时所分的总格数
     */
    private int mTotalCellNum;
    /**
     * 文字的字体大小
     */
    private double mTextFontSize;
    /**
     * 文字的颜色
     */
    private int mTextColor;
    /**
     * 刻度的颜色
     */
    private int mScaleColor;
    /**
     * 顶部的线的颜色
     */
    private int mTopLineColor;
    /**
     * 底部的线的颜色
     */
    private int mBottomLineColor;
    /**
     * 选择时间段背景颜色
     */
    private int mSelectBackgroundColor;
    /**
     * 中间线的颜色
     */
    private int mMiddleLineColor;
    /**
     * 底部线画笔
     */
    private Paint mTopLinePaint;
    /**
     * 底部线画笔
     */
    private Paint mBottomLinePaint;
    /**
     * 刻度线画笔
     */
    private Paint mScaleLinePaint;
    /**
     * 中间线画笔
     */
    private Paint mMiddleLinePaint;
    /**
     * 选择时间段的画笔
     */
    private Paint mSelectPaint;
    /**
     * 文字画笔
     */
    private Paint mTextPaint;
    /**
     * 文字信息
     */
    private Paint.FontMetrics mFontMetrics;
    /**
     * 顶部线的粗度
     */
    private double mTopLineStrokeWidth;
    /**
     * 底部线的粗度
     */
    private double mBottomLineStrokeWidth;
    /**
     * 刻度线的粗度
     */
    private double mScaleLineStrokeWidth;
    /**
     * 中间线的粗度
     */
    private double mMiddleLineStrokeWidth;
    /**
     * 每一格在屏幕上显示的长度
     */
    private double mWidthPerCell;
    /**
     * 每一格代表的毫秒数
     */
    private long mMillisecondPerCell;

    /**
     * 手指移动的距离
     */
    private double mMoveDistance;
    /**
     * 手指最后停留的坐标
     */
    private double mLastX;
    /**
     * 每一像素所占的毫秒数
     */
    private double mMillisecondPerPixel;
    /**
     * 中间条绑定的日历对象
     */
    private Calendar mCalendar;
    private long mTodayStart;
    private long mCurrentTime;
    /**
     * 中间条绑定的日历对象初始毫秒值
     */
    private long mInitMillisecond;
    /**
     * 选择时间回调
     */
    private OnChooseTimeListener onChooseTimeListener;
    /**
     * 需要播放的时间段列表
     */
    private ArrayList<TimeInfo> mTimeInfos = new ArrayList<>();
    /**
     * 回放时间段最小时间点
     */
    private long mMinTime = 0;
    /**
     * 回放时间段最大时间点
     */
    private long mMaxTime = 0;
    /**
     * 是否移动中
     */
    private boolean isMoving = false;
    /**
     * 时间显示高度
     */
    private double mShowTimeHeight;
    /**
     * 三角形开始位置
     */
    private double mArrowStartHeight;
    /**
     * 箭头高度
     */
    private double mArrowHeight;
    /**
     * 箭头margin高度
     */
    private double mArrowMarginHeight;
    /**
     * 时间轴高度
     */
    private double mContentHeight;
    /**
     * 刻度线高度
     */
    private double mScaleHeight;
    /**
     * 刻度开始高度
     */
    private double mContentStartHeight;
    /**
     * 刻度结束高度
     */
    private double mContentEndHeight;
    /**
     * 三角形路径
     */
    private Path mPathTriangle;
    /**
     * 三角形路径
     */
    private Path mPathTriangleBottom;
    /**
     * 时间显示宽度
     */
    private double mShowTimeWidth;
    /**
     * 时间显示矩形范围
     */
    private Rect mShowTimeRec;
    private RectFloat mShowTimeRecF;
    /**
     * 时间显示圆角半径
     */
    private double mShowTimeCorner;
    /**
     * 时间显示矩形画笔
     */
    private Paint mShowTimeRecFPaint;
    /**
     * 时间显示画笔
     */
    private Paint mShowTimePaint;

    private double mShowTimeMarginBottom;
    /**
     * 时间显示动画
     */
    private AnimatorValue mValueAnimator;
    /**
     * 时间显示延迟消失
     */
    private EventHandler mHandler;
    private Runnable mRunnable;

    public TimeRulerView(Context context, AttrSet attrSet) {
        super(context, attrSet);
        mContext = context;
        initDefaultValue(attrSet);
        initPaint();
        initData();
        setBindStateChangedListener(new BindStateChangedListener() {
            @Override
            public void onComponentBoundToWindow(Component component) {
                calculate();
            }

            @Override
            public void onComponentUnboundFromWindow(Component component) {

            }
        });
        setTouchEventListener(this);
        addDrawTask(this);
    }

    @Override
    public void addDrawTask(DrawTask task) {
        super.addDrawTask(task);
        task.onDraw(this, mCanvasForTaskOverContent);
    }

    private void initData() {
        mMillisecondPerCell = 24 * 3600 * 1000 / mTotalCellNum;
        mMillisecondPerPixel = mMillisecondPerCell / mWidthPerCell;
        mShowTimeWidth = mShowTimePaint.measureText(" 00:00:00 ");
        mShowTimeCorner = PxUtil.vp2px(2);
        mScaleHeight = PxUtil.vp2px(5);
        mShowTimeMarginBottom = PxUtil.vp2px(1);
        mArrowStartHeight = mShowTimeHeight + mShowTimeMarginBottom;
        mArrowHeight = PxUtil.vp2px(6);
        mArrowMarginHeight = PxUtil.vp2px(1);
        mScaleHeight = PxUtil.vp2px(5);
        mContentStartHeight = mArrowStartHeight + mArrowHeight + mArrowMarginHeight;
        mContentEndHeight = mContentStartHeight + mContentHeight;
        mPathTriangle = new Path();
        mPathTriangleBottom = new Path();

        mCalendar = Calendar.getInstance();
        mCalendar.set(mCalendar.get(Calendar.YEAR), mCalendar.get(Calendar.MONTH), mCalendar.get(Calendar.DAY_OF_MONTH), 0, 0, 0);
        mInitMillisecond = mCalendar.getTimeInMillis();
        mCurrentTime = mInitMillisecond;
        mTodayStart = mInitMillisecond;

        mHandler = new EventHandler(EventRunner.getMainEventRunner());
        mRunnable = this::startAnimator;
        mValueAnimator = new AnimatorValue();
        mValueAnimator.setDuration(300);
        mValueAnimator.setValueUpdateListener((animatorValue, v) -> {
            int currentValue = (int) (v * 255);
            mShowTimeRecFPaint.setAlpha(currentValue);
            mShowTimePaint.setAlpha(currentValue);
            if (currentValue == 0) {
                isMoving = false;
            }
            invalidate();
        });

//        mHandler = new Handler();
//        mRunnable = this::startAnimator;
//        mValueAnimator = ValueAnimator.ofInt(255, 0);
//        mValueAnimator.setDuration(300);
//        mValueAnimator.addUpdateListener(animation -> {
//            int currentValue = (int) animation.getAnimatedValue();
//            mShowTimeRecFPaint.setAlpha(currentValue);
//            mShowTimePaint.setAlpha(currentValue);
//            if (currentValue == 0) {
//                isMoving = false;
//            }
//            invalidate(mShowTimeRec);
//        });
    }

    public void setTotalCellNum(int mTotalCellNum) {
        //切换刻度，原来的移动距离得倍数处理
        if (mTotalCellNum > this.mTotalCellNum) {
            mMoveDistance *= mTotalCellNum * 1.0F / (this.mTotalCellNum * 1.0F);
        } else {
            mMoveDistance /= this.mTotalCellNum * 1.0F / (mTotalCellNum * 1.0F);
        }
        this.mTotalCellNum = mTotalCellNum;

        mMillisecondPerCell = 24 * 3600 * 1000 / mTotalCellNum;
        mMillisecondPerPixel = mMillisecondPerCell / mWidthPerCell;

        invalidate();
    }

    private void initDefaultValue(AttrSet attrSet) {
        mTotalCellNum = MIDDLE;
        mMiddleLineStrokeWidth = PxUtil.vp2px(3);
        mTextFontSize = AttrUtils.getDimensionFromAttr(attrSet, "textFontSize", 0);
        mBottomLineColor = AttrUtils.getColorFromAttr(attrSet, "bottomLineColor", 0);
        mBottomLineStrokeWidth = AttrUtils.getDimensionFromAttr(attrSet, "bottomLineStrokeWidth", 0);
        mContentHeight = AttrUtils.getDimensionFromAttr(attrSet, "contentHeight", 0);
        mMiddleLineColor = AttrUtils.getColorFromAttr(attrSet, "middleLineColor", 0);
        mScaleColor = AttrUtils.getColorFromAttr(attrSet, "scaleColor", 0);
        mScaleLineStrokeWidth = AttrUtils.getDimensionFromAttr(attrSet, "scaleLineStrokeWidth", 0);
        mSelectBackgroundColor = AttrUtils.getColorFromAttr(attrSet, "selectBackgroundColor", 0);
        mShowTimeHeight = AttrUtils.getDimensionFromAttr(attrSet, "showtimeHeight", 0);
        mTextColor = AttrUtils.getColorFromAttr(attrSet, "textColors", 0);
        mTopLineColor = AttrUtils.getColorFromAttr(attrSet, "topLineColor", 0);
        mTopLineStrokeWidth = AttrUtils.getDimensionFromAttr(attrSet, "topLineStrokeWidth", 0);
        mWidthPerCell = AttrUtils.getDimensionFromAttr(attrSet, "widthPerScale", 0);
    }

    private void initPaint() {
        mTopLinePaint = new Paint();
        mTopLinePaint.setAntiAlias(true);
        mTopLinePaint.setColor(new Color(mTopLineColor));
        mTopLinePaint.setStyle(Paint.Style.STROKE_STYLE);
        mTopLinePaint.setStrokeWidth( (float)mTopLineStrokeWidth);

        mBottomLinePaint = new Paint();
        mBottomLinePaint.setAntiAlias(true);
        mBottomLinePaint.setColor(new Color(mBottomLineColor));
        mBottomLinePaint.setStyle(Paint.Style.STROKE_STYLE);
        mBottomLinePaint.setStrokeWidth((float)mBottomLineStrokeWidth);

        mScaleLinePaint = new Paint();
        mScaleLinePaint.setAntiAlias(true);
        mScaleLinePaint.setColor(new Color(mScaleColor));
        mScaleLinePaint.setStyle(Paint.Style.STROKE_STYLE);
        mScaleLinePaint.setStrokeWidth((float)mScaleLineStrokeWidth);

        mMiddleLinePaint = new Paint();
        mMiddleLinePaint.setAntiAlias(true);
        mMiddleLinePaint.setColor(new Color(mMiddleLineColor));
        mMiddleLinePaint.setStyle(Paint.Style.STROKE_STYLE);
        mMiddleLinePaint.setStrokeWidth((float)mMiddleLineStrokeWidth);

        mSelectPaint = new Paint();
        mSelectPaint.setAntiAlias(true);
        mSelectPaint.setColor(new Color(mSelectBackgroundColor));
        mSelectPaint.setStyle(Paint.Style.FILL_STYLE);

        mTextPaint = new Paint();
        mTextPaint.setAntiAlias(true);
        mTextPaint.setColor(new Color(mTextColor));
        mTextPaint.setStyle(Paint.Style.FILL_STYLE);
        mTextPaint.setTextAlign(TextAlignment.CENTER);
        mTextPaint.setTextSize((int) mTextFontSize);

        mFontMetrics = mTextPaint.getFontMetrics();

        mShowTimeRecFPaint = new Paint();
        mShowTimeRecFPaint.setAntiAlias(true);
        mShowTimeRecFPaint.setColor(new Color(Color.getIntColor("#000000")));
        mShowTimeRecFPaint.setStyle(Paint.Style.FILL_STYLE);

        mShowTimePaint = new Paint();
        mShowTimePaint.setAntiAlias(true);
        mShowTimePaint.setColor(new Color(Color.getIntColor("#E6FFFFFF")));
        mShowTimePaint.setStyle(Paint.Style.FILL_STYLE);
        mShowTimePaint.setTextAlign(TextAlignment.CENTER);
        mShowTimePaint.setTextSize((int) PxUtil.fp2px(14));
    }

    private void calculate() {
        double mMiddleLineX = getWidth() / 2.0F;
        if (mMiddleLineX != 0 && mShowTimeRec == null) {
            mPathTriangle.reset();
            mPathTriangle.moveTo((float)(mMiddleLineX - mArrowHeight / 2.0F), (float)mArrowStartHeight);
            mPathTriangle.lineTo((float)(mMiddleLineX + mArrowHeight / 2.0F), (float)mArrowStartHeight);
            mPathTriangle.lineTo((float)mMiddleLineX, (float)(mArrowStartHeight + mArrowHeight));
            mPathTriangle.close();

            mPathTriangleBottom.reset();
            mPathTriangleBottom.moveTo((float)mMiddleLineX, (float)(mContentEndHeight + mArrowMarginHeight));
            mPathTriangleBottom.lineTo((float)(mMiddleLineX - mArrowHeight / 2.0F), (float)(mContentEndHeight + mArrowMarginHeight + mArrowHeight));
            mPathTriangleBottom.lineTo((float)(mMiddleLineX + mArrowHeight / 2.0F), (float)(mContentEndHeight + mArrowMarginHeight + mArrowHeight));
            mPathTriangleBottom.close();

            mShowTimeRec = new Rect((int) (mMiddleLineX - mShowTimeWidth / 2.0F), 0,
                    (int) (mMiddleLineX + mShowTimeWidth / 2.0F), (int) mShowTimeHeight);
            mShowTimeRecF = new RectFloat((float)(mMiddleLineX - mShowTimeWidth / 2.0F), 0,
                    (float)(mMiddleLineX + mShowTimeWidth / 2.0F), (float)mShowTimeHeight);
        }
    }

    @Override
    public void onDraw(Component component, Canvas canvas) {
        drawTimeInfos(canvas);
        drawTopLine(canvas);
        drawBottomLine(canvas);
        drawMiddleLine(canvas);
        drawScaleLineDynamic(canvas);
    }

    private void drawTopLine(Canvas canvas) {
        canvas.drawLine(new Point(0, (float)mContentStartHeight), new Point(getWidth(),(float) mContentStartHeight), mTopLinePaint);
    }

    /**
     * 绘制时间块
     *
     * @param canvas the canvas
     */
    private void drawTimeInfos(Canvas canvas) {
        if (mTimeInfos != null) {
            for (TimeInfo timeInfo : mTimeInfos) {
                double start = getWidth() / 2.0F - (mCurrentTime - timeInfo.startTime.getTimeInMillis()) / mMillisecondPerPixel;
                double end = getWidth() / 2.0F + (timeInfo.endTime.getTimeInMillis() - mCurrentTime) / mMillisecondPerPixel;
                canvas.drawRect(new RectFloat((float)start,(float) mContentStartHeight, (float)end, (float)mContentEndHeight), mSelectPaint);
            }
        }
    }

    /**
     * 画中间线
     *
     * @param canvas 画笔
     */
    private void drawMiddleLine(Canvas canvas) {
        mMiddleLinePaint.setStyle(Paint.Style.STROKE_STYLE);
        Point startP = new Point(getWidth() / 2.0F,(float) mContentStartHeight);
        Point endP = new Point(getWidth() / 2.0F, (float)mContentEndHeight);
        canvas.drawLine(startP, endP, mMiddleLinePaint);
        mMiddleLinePaint.setStyle(Paint.Style.FILL_STYLE);
        canvas.drawPath(mPathTriangle, mMiddleLinePaint);
        canvas.drawPath(mPathTriangleBottom, mMiddleLinePaint);
    }

    /**
     * 画刻度线和文字
     *
     * @param canvas the canvas
     * @author huanghao6 Created on 2018-07-19
     */
    private void drawScaleLineDynamic(Canvas canvas) {
        if (isMoving) {
            //移动中，显示移动到的时间
            canvas.drawRoundRect(mShowTimeRecF,(float) mShowTimeCorner, (float)mShowTimeCorner, mShowTimeRecFPaint);
            double baseLineY = (mArrowStartHeight - mFontMetrics.top - mFontMetrics.bottom) / 2.0F;//基线中间点的y轴计算公式
            canvas.drawText(mShowTimePaint, formatterMove.format(mCurrentTime), getWidth() / 2.0F, (float)baseLineY);
        }
        // 刻度线数量根据可见的刻度数量动态变化
        double totalWidth = getWidth();

        int showCell;
        if (mTotalCellNum >= TOPMIDDLE) {
            showCell = FIVEMIN;
        } else if (mTotalCellNum >= MIDDLE) {
            showCell = FIFTEENMIN;
        } else if (mTotalCellNum >= DOWNMIDDLE) {
            showCell = HALFHOUR;
        } else {
            showCell = HOUR;
        }
        int unitMinutes = 24 * 60 / showCell;
        int unitCount = 24 * 60 / unitMinutes;
        long unitTime;
        for (int i = 0; i <= unitCount; i++) {
            unitTime = mTodayStart + i * unitMinutes * 60 * 1000;
            double distance = (unitTime - mCurrentTime) / mMillisecondPerPixel;

            double XFromMiddlePoint = totalWidth / 2.0F + distance;
            Point sp1 = new Point((float)XFromMiddlePoint, (float)(mContentEndHeight - mScaleHeight));
            Point ep1 = new Point((float)XFromMiddlePoint,(float) mContentEndHeight);
            canvas.drawLine(sp1, ep1, mScaleLinePaint);
            Point sp2 = new Point((float)XFromMiddlePoint,(float) mContentStartHeight);
            Point ep2 = new Point((float)XFromMiddlePoint, (float)(mContentStartHeight + mScaleHeight));
            canvas.drawLine(sp2, ep2, mScaleLinePaint);
            if (i % 2 == 0) {
                drawTextDynamic(i, unitMinutes, XFromMiddlePoint, canvas);
            }
        }
    }

    private void drawTextDynamic(int i, int unitMinutes, double moveX, Canvas canvas) {
        double baseLineY = mContentStartHeight + (mContentHeight - mFontMetrics.top - mFontMetrics.bottom) / 2.0F;//基线中间点的y轴计算公式
        int minuteOffset = i * unitMinutes;
        int hour = minuteOffset / 60;
        int minute = minuteOffset % 60;
        String time = String.format(Locale.CHINA, "%02d:%02d", hour, minute);
        canvas.drawText(mTextPaint, time, (float)moveX, (float)baseLineY);
    }

    /**
     * 画水平长线
     *
     * @param canvas 画笔
     */
    private void drawBottomLine(Canvas canvas) {
        canvas.drawLine(new Point(0, (float)mContentEndHeight), new Point(getWidth(), (float)mContentEndHeight), mBottomLinePaint);
    }

    @Override
    public boolean onTouchEvent(Component component, TouchEvent event) {
        if (event.getPointerPosition(0).getY() >= mContentStartHeight) {
            //只有点击刻度范围内才有效
            if (mMaxTime > mMinTime) {
                switch (event.getAction()) {
                    case TouchEvent.PRIMARY_POINT_DOWN:
                        mLastX = event.getPointerPosition(0).getX();
                        break;
                    case TouchEvent.POINT_MOVE:
                        double mPointXoff = event.getPointerPosition(0).getX() - mLastX;
                        mLastX = event.getPointerPosition(0).getX();
                        if (Math.abs(mPointXoff) < TOUCH_SLOP) {
                            return true;
                        }
                        isMoving = true;
                        initAnimator();
                        mMoveDistance += mPointXoff;
                        //移动小于最小值、或大于最大值，进行校正，不让用户移过去
                        long temp = mInitMillisecond - (long) (mMoveDistance * mMillisecondPerPixel);
                        if (mMinTime != 0 && temp < mMinTime) {
                            temp = mMinTime;
                            mMoveDistance = (mInitMillisecond - mMinTime) / mMillisecondPerPixel;
                        } else if (mMaxTime != 0 && temp > mMaxTime) {
                            temp = mMaxTime;
                            mMoveDistance = (mInitMillisecond - mMaxTime) / mMillisecondPerPixel;
                        }
                        mCurrentTime = temp;
                        invalidate();
                        break;
                    case TouchEvent.CANCEL:
                    case TouchEvent.PRIMARY_POINT_UP:
                        if (isMoving) {
                            mHandler.removeTask(mRunnable);
                            mHandler.postTask(mRunnable, 500);
                            if (onChooseTimeListener != null) {
                                mCalendar.setTimeInMillis(mCurrentTime);
                                onChooseTimeListener.onChooseTime(mCalendar);
                            }
                        }
                        break;
                    default:
                        break;
                }
            }
            return true;
        } else {
            if (isMoving) {
                switch (event.getAction()) {
                    case TouchEvent.CANCEL:
                    case TouchEvent.PRIMARY_POINT_UP:
                        mHandler.removeTask(mRunnable);
                        mHandler.postTask(mRunnable, 500);
                        if (onChooseTimeListener != null) {
                            mCalendar.setTimeInMillis(mCurrentTime);
                            onChooseTimeListener.onChooseTime(mCalendar);
                        }
                        break;
                }
            }
            return true;
        }
    }

    /**
     * 还原动画
     */
    private void initAnimator() {
        mShowTimeRecFPaint.setAlpha(255);
        mShowTimePaint.setAlpha(255);
    }

    /**
     * 开始动画
     */
    private void startAnimator() {
        initAnimator();
        mValueAnimator.cancel();
        mValueAnimator.start();
    }

    public boolean isMoving() {
        return isMoving;
    }

    public void setOnChooseTimeListener(OnChooseTimeListener onChooseTimeListener) {
        this.onChooseTimeListener = onChooseTimeListener;
    }

    /**
     * 日历切换开始的时候，复位时间轴
     */
    public void reset() {
        mMinTime = mMaxTime = 0;
        mCurrentTime = mTodayStart;
        invalidate();
    }

    public void setTime(Calendar calendar) {
        if (calendar != null) {
            mCurrentTime = calendar.getTimeInMillis();
            if (mCalendar.get(Calendar.YEAR) != calendar.get(Calendar.YEAR)
                    || (mCalendar.get(Calendar.YEAR) == calendar.get(Calendar.YEAR)
                    && mCalendar.get(Calendar.MONTH) != calendar.get(Calendar.MONTH))
                    || (mCalendar.get(Calendar.YEAR) == calendar.get(Calendar.YEAR)
                    && mCalendar.get(Calendar.MONTH) == calendar.get(Calendar.MONTH)
                    && mCalendar.get(Calendar.DAY_OF_MONTH) != calendar.get(Calendar.DAY_OF_MONTH))) {
                //不是同一天
                Calendar mCalendar = Calendar.getInstance();
                mCalendar.set(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH), calendar.get(Calendar.DAY_OF_MONTH), 0, 0, 0);
                mInitMillisecond = mCalendar.getTimeInMillis();
                mTodayStart = mInitMillisecond;
            }
            mCalendar.setTimeInMillis(calendar.getTimeInMillis());
            mMoveDistance = (mInitMillisecond - mCurrentTime) / mMillisecondPerPixel;
        }
    }

    public void setTimeInfos(ArrayList<TimeInfo> timeInfos) {
        this.mTimeInfos.clear();
        if (timeInfos != null) {
            this.mTimeInfos.addAll(timeInfos);
        }
        if (!this.mTimeInfos.isEmpty()) {
            long minTime = this.mTimeInfos.get(0).startTime.getTimeInMillis();
            long maxTime = this.mTimeInfos.get(0).endTime.getTimeInMillis();
            for (TimeInfo timeInfo : this.mTimeInfos) {
                if (timeInfo.startTime.getTimeInMillis() < minTime) {
                    minTime = timeInfo.startTime.getTimeInMillis();
                }
                if (timeInfo.endTime.getTimeInMillis() > maxTime) {
                    maxTime = timeInfo.endTime.getTimeInMillis();
                }
            }
            mMinTime = minTime;
            mMaxTime = maxTime;
        } else {
            mMinTime = mMaxTime = 0;
        }
    }

    public interface OnChooseTimeListener {
        void onChooseTime(Calendar calendar);
    }

    public static class TimeInfo {
        public Calendar startTime;
        public Calendar endTime;

        public TimeInfo(Calendar startTime, Calendar endTime) {
            this.startTime = startTime;
            this.endTime = endTime;
        }
    }
}